var w = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;

var h = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;

id选择器 #
类选择器 .
标签选择器 div h1 p
相邻选择器 h1 + p
子选择器 ul > li 
后代选择器 li a 
通配符选择器 * 
属性选择器 a[rel="extend"]
伪类选择器 a:hover, li:nth-child


css3 新特性

过渡

动画

选择器

阴影 （文字阴影text-shadow、盒子阴影box-shadow）

<meta name="viewport" content="width=device-width, initail-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
  initail-scale: 初始的缩放比例
  minimum-scale: 允许用户缩放到的最小比例
  maximum-scale: 允许用户缩放到的最大比例
  user-scaleable: 用户是否可以手动缩放
</meta>



js 基本数据类型

5种简单数据类型(基本数据类型) + 1 种复杂数据类型

undefined number string null boolean +  object 

console.log('script start');
console.log('async1 start');
console.log('async2');
console.log('promise1');
console.log('script end');
console.log('async1 end');
console.log('promise2');
console.log('setTimeout');

string number boolean null undefined object 

typeof 优点：能够快速区分基本数据类型， 缺点：不能讲Object，Array和Null 区分，都返回object

instanceof 优点：能够区分Array，object和function，适合用于判断自定义的类实例对象。 缺点：number，boolean，string基本数据类型不能判断

Object.prototype.toString.call() 
let toSring = Object.prototype.toString;
console.log(toString.call(1)) //[object Number]

Object.prototype.toString.call() 优点：精准判断数据类型  缺点：写法繁琐不容易记，推荐进行封装后使用


原型ajax
如何创建Ajax
XMLHttpRequest对象的工作流程
==========兼容性写法===========
var xmlHttp = null;
if(window.XMLHttpRequset) {
	// IE7+,Firefox,Chrome,Safari,Opera
	xmlHttp = new XMLHttpRequset();
}
else {
	// IE5,IE6
	xmlHttp = new ActiveXObject("Microsoft.XMLHTTP")
}
兼容性处理
事件的触发条件
xmlHttp.onreadystatechange = function() {
	if(xmlHttp.readyState == 4 && xmlHttp.status == 200) {
		responseText、responseXML
	}
}
事件的触发顺序
======================注意=================
如果是POST请求则需要添加头
xmlHttp.setRequestHeader("Content-type": "application/x-www-form-urlencoded")


冒泡事件是从内向外；捕获是从外向内======document->html->body->div
    DOM事件流
一个完整的事件流分为三个阶段：捕获-》目标阶段-》冒泡=========事件通过捕获到达目标元素再从目标元素通过冒泡上传到元素
    描述DOM事件捕获的具体流程
捕获：window->document->html->body->......->目标元素
冒泡：相反


深拷贝
1.1最简单的方法就是JSON.parse(JSON.stringify()),但是这种拷贝方法不可以拷贝一些特殊的属性（例如正则表达式，undefined，function）
1.2 用递归去复制所有层级属性

function deepCopyTwo (obj) {
  let objClone = Array.isArray(obj) ? [] : {};
  if (obj && typeof obj == 'object') {
    for (const key in obj) {
      // 判断obj子元素是否是对象，如果是，递归复制
      if (obj[key] && typeof obj[key] === 'object') {
        objClone[key] = deepCopyTwo(obj[key])
      } else {
        // 如果不是，简单复制
        objClone[key] = obj[key]
      }
    }
  }
  return objClone;
}

浅拷贝
Object.assign(target, ...sources)

function simpleClone (obj) {
  let result = {};
  for(let i in obj) {
    result[i] = obj[i]
  }
  return result;
}


获取盒子宽高的几种方式及区别：

1.获取选然后的宽高：
	dom.currentStyle.width/height
	
	window.getComputedStyle(dom).width/height
	
	dom.getBoundingClientRect().width/height
	
	
1. px：绝对单位，页面按精确像素展示
2. em：相对单位，基准点为父节点字体的大小，如果自身定义了font-size按自身来计算（浏览器默认字体是16px），整个页面内1em不是一个固定的值
3. rem：相对单位，可理解为”root em”, 相对根节点html的字体大小来计算，CSS3新加属性，chrome/firefox/IE9+支持
4. vw：viewpoint width，视窗宽度，1vw等于视窗宽度的1%
5. vh：viewpoint height，视窗高度，1vh等于视窗高度的1%
6. vmin：vw和vh中较小的那个
7. vmax：vw和vh中较大的那个
8. %:百分比


三种css预处理器都有：嵌套、运算符、颜色函数、导入、继承、混入。Stylus还有一些高级特性。例如循环、判断等


判断数据类型: Object.prototype.toSring.call(*);


// 对象深浅拷贝
1. 深拷贝 
1.1 最简单的方法就是JSON.parse(JSON.stringify())
	但是这种拷贝方法不可以拷贝一些特殊的属性(例如正则表达式，undefined，function)
1.2 用递归去复制所有层级属性

function deepCopyTwo (obj) {
	let objClone = Array.isArray(obj) ? [] : {};
	if (obj && typeof obj == 'object') {
		for(let key in obj) {
			// 如果obj子对象是对象，递归复制
			if (obj[key] && obj[key] === 'object') {
				objClone[key] = deepCopyTwo(obj[key]);
			} else {
				// 如果不是，简单复制
				objClone[key] = obj[key];
			}
		}
	}
	return objClone;
}


// 浅拷贝
Object.assign(targer, ...sources);

function simpleClone (obj) {
	let result = {};
	for (let i in obj) {
		result[i] = obj[i];
	}
	return result;
}



数据分为基本数据类型和引用数据类型

1.基本数据类型：
	String, Number, Boolean, Null, Undefined
	
	基本数据类型是直接存储在栈中的数据
	
2.引用数据类型：
	Array, Object
	
	引用数据类习性存储的是该对象在栈中引用，真是的数据存储在内存中
	
深拷贝和浅拷贝的概念

浅拷贝：仅仅复制对象的引用，而不是对象本身
深拷贝：把复制的对象所引用的全部对象都复制一遍

浅拷贝:
	object.assign();
	
	concat, slice 不会改变原数组
	
	
深拷贝：
	递归复制
	JSON.parse(JSON.stringify())
	JSON.stringify();把一个js对象序列化为一个JSON字符串
	JSON.parse();把JSON字符串反序列化为一个js对象
	
	
promise 初体验 （异步编程）

一个最基本的Promise长什么样？
[index.js]
	new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(1)
    })
	}).then(value => {
		console.log('value',value)
	},reason => {
		console.log('reason',reason)
	})

	运行结果： value 1
	


 函数柯里化：柯里化是把接收多个参数的函数变成接受一个单一参数(最初韩束的第一个参数)的函数，并且返回其余参数和接口和新函数的技术
 
 
 改变this的指向：
  bind, call, apply 用法及区别 

相同点：三个函数的作用就是改变this的指向，将函数绑定到上下文中；
不同点：三个函数的语法不同

fun.call(thisArg[, arg1[, arg2[, ...]]])
fun.apply(thisArg, [argsArray])
var bindFn = fun.bind(thisArg[, arg1[, arg2[, ...]]])
bindFn()

扩展：手写三个函数的源码
	1. 手写apply源码
	Function.prototype.apply = function (content = window) {
		content.fn = this;
		let result;
		// 判断是否有第二个参数
		if (arguments[1]) {
			result = content.fn(...arguments[1]);
		} else {
			result = content.fn();
		}
		delete content.fn;
		return result;
	}
	
	2.手写call源码
	/**
	*	完整版步骤
	*	将函数设为对象属性
	*	执行&删除这个函数
	*	指定this到函数并传入给定参数执行函数
	*	如果不传参数，默认指向window
	**/
	
	Function.prototype.call = function(content = window) {
		// 判断是否是underfine 和 null
		// if (typeof content === 'undefined' || typeof content === null) {
			// content = window
		//}
		content.fn = this;
		let args = [...arguments].slice(1);
		let result = content.fn(...args);
		delete content.fn;
		return result;
	}
	
	3.手写bind源码
	/**
	*	bind() 方法
	*	会创建一个新函数，当这个新函数被调用时，bind() 的第一个参数将作为它运行时的this，之后的一序列参数将会在传递的实参前传入作为它的参数。
	**/
	Function.prototype.bind = function(content){
		if (typeof this != 'function') {
			throw Error('not a function');
		}
		let _this = this;
		let args = [...arguments].slice(1);
		return function F(){
			// 判断是否被当做构造函数使用
			if(this instanceof F){
				return _this.apply(this, args.concat([...arguments]))
			}
			return _this.apply(content, args.concat([...arguments]))
		}
	}
	
	
	创建对象几种方法：
	
	// 第一种：字面量
	var o1 = { name: "o1"}
	var o2 = new Object({name: "o2"});
	
	// 第三种：Object.create()
	var p = { name: "p"}
	var o4 = Object.create(p)
	
	// 第二种：通过构造函数
	var M = function(name){this.name = name}
	var o3 = new M("o3")

	
	Vue -  对于 MVC && MVVM 的理解
	
	MVC： M代表模型层、V代表视图层、C代表控制器层，
	

	MVVM 设计模式，是由MVC(最早来源于后端)、MVP等设计模式进化而来。
	
	1.M - 数据模型（model），简单的js对象
	2.V - 视图层 （View）, 呈现给用户的DOM渲染界面
	3.VM - 视图模型 （ViewModel），连接Model与View
	
	---- 
	通过MVVM模式图，我们可以看出最核心的就是viewmodel，它主要的作用：对view中dom元素的监听和对odel中数据进行绑定，当view变化会引起model中数据的改动，model中数据的改动会触发view视图重新渲染，从而达到数据双向绑定的效果，该效果也是vue最为核心的特性。
	
	// 常见库实现数据双向绑定的做法：
	。发布订阅模式（backbone.js）
	。脏值检查（angular.js）
	。数据劫持（vue.js）
	
	VUE的双向绑定原理：
		vue是采用数据劫持结合发布订阅模式，通过object.defineProperty()来劫持各个属性的getter，setter，在数据变动时发布消息给订阅者，触发相应的回调函数，从而实现数据双向绑定。
	
	Virtual dom的理解
	
	一、什么是vdom？ 虚拟dom， 用js模拟dom结构
	
	二、为何要用vdom？
	1. DOM操作非常非常“rang贵”，将DOM对比操作放在JS层，提高效率
	2. DOM结构的对比，放在JS层来做（图灵完备语言：能实现逻辑代码的语言）
	
	
	三、vdom核心函数有哪些
	核心函数：
	h('标签名', {...属性名...}, [...子元素...])
	h('标签名', {...属性名...}, '.........')
	patch(container, vnode)
	patch(vnode, newVnode)
	
	
	
	webpack作用：
	
	1.ES6/7/8/9等高级语法转换es5
	2.scss/less/stylus等css预处理器转换成css
	3.解析字体font，图片等静态资源
	4.压缩js、css等文件
	5.自动添加css各大浏览器厂商前缀
	6.定义环境变量
	7.抽离公共代码
	8.项目热更新和懒加载
	9.区别生产环境和开发环境
	10.每次打包删除上一次打包记录





















	
	
	
	
	
	
	
	
	
	